package logica;

import java.util.ArrayList;
import java.util.Collection;
import mapa.Coordenada;
import terrenos.Terreno;
import unidades.Unidad;
import unidades.UnidadHT;

public class AccionAtacar implements Accion {

    public static final int UNIDAD_ATACANTE = 0;
    public static final int UNIDAD_DEFENSORA = 1;

    /**
     * Crea una acción de ataque para atacar con la unidad actual a otra en su rango. 
     * Su ejecución devolverá List<Coordenada> con la unidad atacante y la defensora.
     * Se pueden obtener los datos mediante los atributos estáticos de esta clase
     * de la siguiente forma: nombredelacollection.get(AccionAtacar.UNIDAD_ATACANTE);
     * Si la unidad defensora muere, su coordenada pasara a ser null
     */
    public AccionAtacar() {
    }

    /**
     * Realiza el ataque de la unidad sobre otra casilla. Si es correcto, devuelve ambas 
     * unidades en una Collection<Coordenada> de la que se pueden sacar los datos con los 
     * atributos estáticos en la clase
     * 
     * @param args Array con los argumentos necesarios. 
     * Debe recibir los parámetros en el siguiente orden:
     * <ol><li>ModeloHT</li>
     * <li>UnidadHT</li>
     * <li>Collection<Coordenada> rangoMovimiento</li>
     * <li>Collection<Coordenada> rangoAtaque</li>
     * <li>Coordenada</li></ol>
     * @return List<Coordenada> con la unidad atacante y la defensora
     */
    public Object ejecutarAccion(Object... args) {
        ModeloHT modelo = (ModeloHT) args[0];
        UnidadHT unidadActual = (UnidadHT) args[1];
        Collection<Coordenada> rangoAtqActual = (Collection<Coordenada>) args[3];
        Coordenada crdnd = (Coordenada) args[4];
        if (rangoAtqActual.isEmpty()) {
            throw new NullPointerException("No se ha establecido el rango de ataque de la unidad");
        }
        if (!unidadActual.puedeAtacar()) {
            throw new IllegalStateException("La unidad actual no puede atacar porque ya ha realizado otra acción");
        }
        //Si no quedan puntos de accion y la unidad puede moverse, no puede hacer nada
        //Si no quedan pero no puede moverse, ha movido pero no atacado, así que es legal
        if (modelo.getPartida().getTurno().getPuntosAccion() <= 0 && unidadActual.puedeMover()) {
            return null;
        }
        if (rangoAtqActual.contains(crdnd) && modelo.getPartida().getMapa().getContenidoCasilla(crdnd) != null) {
            UnidadHT clicCasilla = (UnidadHT) modelo.getPartida().getMapa().getContenidoCasilla(crdnd);
            if (modelo.getPartida().getTurno().getJugadorActivo().getEquipo().contains(clicCasilla)) {
                return null;
            }
            UnidadHT enemigo = (UnidadHT) modelo.getPartida().getMapa().getContenidoCasilla(crdnd);
            Terreno terreno = (Terreno) modelo.getPartida().getMapa().getCasilla(crdnd);
            int danyo = unidadActual.ATAQUE - terreno.getBonificacion(enemigo);
            if (danyo > 0) {
                int nuevaVit = enemigo.getVidaPartida() - danyo;
                if (nuevaVit <= 0) {
                    enemigo.setVidaPartida(0);
                    modelo.getPartida().getMapa().setPosicion(null, enemigo.getPosicion());
                    if(modelo.getPartida().getTurno().getJugadorActivo() == modelo.getPartida().getJugadorA()) {
                        modelo.getPartida().getJugadorB().getEquipo().getUnidades().remove(enemigo);
                    } else {
                        modelo.getPartida().getJugadorA().getEquipo().getUnidades().remove(enemigo);
                    }
                } else {
                    enemigo.setVidaPartida(nuevaVit);
                }
            }
            //Si se podía mover, ha perdido su opción de movimiento y se resta un punto de acción.
            //Si ya no se podía mover, es que ya ha hecho un movimiento, por tanto ya se ha
            //restado un punto de acción, así que no se actualiza
            rangoAtqActual.clear();
            ArrayList<Coordenada> coords = new ArrayList<Coordenada>();
            coords.add(unidadActual.getPosicion());
            coords.add(crdnd);
            modelo.actualizarTurno();
            unidadActual.atacado();
            return coords;
        }
        return null;
    }
}
